﻿using System;
using System.Runtime.CompilerServices;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.Assertions;

namespace Nirvana
{
    [CustomEditor(typeof(AnimatorParameterGroup))]
    public class AnimatorParameterGroupEditor : Editor
    {
        private SerializedProperty animator;
        private SerializedProperty activeOnInitialize;
        private SerializedProperty parameters;

        private ReorderableList reorderlist;
        private void OnEnable()
        {
            this.animator = serializedObject.FindProperty("animator");
            this.activeOnInitialize = serializedObject.FindProperty("activeOnInitialize");
            this.parameters = serializedObject.FindProperty("parameters");

            this.reorderlist = new ReorderableList(serializedObject, this.parameters);
            this.reorderlist.drawHeaderCallback = DrawHeaderEnter;
            this.reorderlist.elementHeight = 2f * EditorGUIUtility.singleLineHeight;
            this.reorderlist.drawElementCallback = DrawElement;

        }

        public override void OnInspectorGUI()
        {
            base.serializedObject.Update();
            EditorGUILayout.PropertyField(this.animator);
            AnimatorParameterGroup animatorParameterGroup = (AnimatorParameterGroup)this.target;
            Animator _animator = animatorParameterGroup.GetAnimator();
            if (_animator == null || _animator.runtimeAnimatorController == null)
            {
                EditorGUILayout.HelpBox("The animator is not valid.", MessageType.Warning);
            }
            else
            {
                _animator.Rebind();
                EditorGUILayout.PropertyField(this.activeOnInitialize);
                PrefabType prefabType = PrefabUtility.GetPrefabType(animatorParameterGroup.gameObject);
                if (prefabType == PrefabType.Prefab)
                {
                    EditorGUILayout.HelpBox("Can not edit the parameters in prefab.", MessageType.Warning);
                }
                else
                {
                    this.reorderlist.DoLayoutList();
                }
            }
            base.serializedObject.ApplyModifiedProperties();
            if (GUILayout.Button("SetParameters"))
            {
                animatorParameterGroup.SetParameters();
            }
        }


        private void DrawHeaderEnter(Rect rect)
        {
            GUI.Label(rect, "Parameters:");
        }
        private void DrawElement(Rect rect, int index, bool isActive, bool isFocused)
        {
            SerializedProperty arrayElementAtIndex = this.parameters.GetArrayElementAtIndex(index);
            SerializedProperty Name = arrayElementAtIndex.FindPropertyRelative("Name");
            SerializedProperty ID = arrayElementAtIndex.FindPropertyRelative("ID");
            SerializedProperty ParameterType = arrayElementAtIndex.FindPropertyRelative("ParameterType");
            SerializedProperty BooleanValue = arrayElementAtIndex.FindPropertyRelative("BooleanValue");
            SerializedProperty IntegerValue = arrayElementAtIndex.FindPropertyRelative("IntegerValue");
            SerializedProperty FloatValue = arrayElementAtIndex.FindPropertyRelative("FloatValue");

            Rect r = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
            AnimatorParameterGroup animatorParameterGroup = (AnimatorParameterGroup)this.target;
            Animator animator = animatorParameterGroup.GetAnimator();
            Assert.IsNotNull<Animator>(animator);
           
            if (animator.parameters == null || animator.parameterCount == 0)
            {
                GUI.enabled = false;
                EditorGUI.PropertyField(r, Name);
                r.y += EditorGUIUtility.singleLineHeight;
                EditorGUI.PropertyField(r, FloatValue, new GUIContent("Value:"));
                GUI.enabled = true;
                return;
            }
            int selectIndex = -1;
            string[] paramnames = new string[animator.parameterCount];
            for(int i = 0; i < animator.parameterCount; i++)
            {
                var p = animator.parameters[i];
                paramnames[i] = p.name;
                if(p.nameHash  == ID.intValue)
                {
                    selectIndex = i;
                }
            }

            EditorGUI.BeginChangeCheck();
            selectIndex = EditorGUI.Popup(r, selectIndex, paramnames);
            if (EditorGUI.EndChangeCheck())
            {
                Name.stringValue = paramnames[selectIndex];
                ID.intValue = Animator.StringToHash(Name.stringValue);
            }
            UnityEngine.AnimatorControllerParameterType parameterType = UnityEngine.AnimatorControllerParameterType.Bool;
            foreach(var p in animator.parameters)
            {
                if(p.nameHash == ID.intValue)
                {
                    parameterType = p.type;
                    ParameterType.intValue = (int)parameterType;
                }
            }
            r.y += EditorGUIUtility.singleLineHeight;
            switch (parameterType)
            {
                case UnityEngine.AnimatorControllerParameterType.Float:
                    EditorGUI.PropertyField(r, FloatValue, new GUIContent("Value:"));
                    break;
                case UnityEngine.AnimatorControllerParameterType.Int:
                    EditorGUI.PropertyField(r, IntegerValue, new GUIContent("Value:"));
                    break;
                case UnityEngine.AnimatorControllerParameterType.Bool:
                    EditorGUI.PropertyField(r, BooleanValue, new GUIContent("Value:"));
                    break;
                default:
                    if (parameterType != UnityEngine.AnimatorControllerParameterType.Trigger) return;
                    EditorGUI.PropertyField(r, BooleanValue, new GUIContent("Value:"));
                    break;

            }
        }
    }
}

